package org.hackystat.sdsa.analyzer.model.activity;

import java.util.Map;
import java.util.logging.Logger;

import javax.xml.datatype.XMLGregorianCalendar;

import jess.Fact;
import jess.JessException;
import jess.RU;
import jess.Rete;
import jess.Value;

import org.hackystat.sdsa.analyzer.control.SensorDataUtil;
import org.hackystat.sensorbase.resource.sensordata.jaxb.SensorData;

/**
 * Defines UnitTestActivity.
 * 
 * @author hongbing
 *
 */
public class UnitTestActivity extends Activity {
  /** Success value. */
  private String success = "true";
  /** Test-case name. */
  private String testcase;
  /** Failure message. */
  private String failureMessage = "";
  /** Run time. */
  private XMLGregorianCalendar runTime; 
  /** Elapsed time. */
  private int elapsedTime;
  
  /** Total number of tests. */
  private int testCount;
  /** Index of test case. */
  private int testIndice;
  
  /** Elapsed time property . */
  public static final String ELAPSED_TIME = "elapsedtime";
  /** Failure string property.*/
  public static final String FAILURE_STRING = "failurestring";
  /** Error string property. */
  public static final String ERROR_STRING = "errorstring";
  /** Test case property. */
  public static final String TEST_CASE = "testcase";
  /** Test name property. */
  public static final String TEST_NAME = "testname";
  /** Test count property. */
  public static final String TEST_COUNT = "testcount";
  /** Test indice property. */
  public static final String TEST_INDICE = "testindice";
  /** Activity Type */
  private static final String TYPE = "UNIT TEST";

  /**
   * A dummy UnitTestActivity constructor without sensordata.
   */
  public UnitTestActivity() {
    this.success = "true";
  }
  
  /**
   * Instantiates an instance.
   * 
   * @param sensorData Sensor data.
   * @param logger Service logger.
   */
  public UnitTestActivity(SensorData sensorData, Logger logger) {
    super(sensorData, logger);
    super.setType(TYPE);
    Map<String, String> propMap = SensorDataUtil.propMap(sensorData);
    String failureMessage = propMap.get(FAILURE_STRING);
    if (failureMessage != null && !"".equals(failureMessage.trim())) {
      this.failureMessage = failureMessage;
      this.success = "false";
    }
    
    //String runTimeString = propMap.get(RUN_TIME);
    this.runTime = sensorData.getRuntime();
    
    String testCountString = propMap.get(TEST_COUNT);
    this.testCount = Integer.parseInt(testCountString);

    String testIndiceString = propMap.get(TEST_INDICE);
    this.testIndice = Integer.parseInt(testIndiceString);
  
    String elapsedTimeString = propMap.get(ELAPSED_TIME);
    this.elapsedTime = Integer.parseInt(elapsedTimeString);
  }
  
  /**
   * Gets number of total test count in this test run.
   * 
   * @return Number of test counts.
   */
  public int getTestCount() {
    return this.testCount;
  }
  
  /***
   * Get the indice of this test activity.
   * 
   * @return Index of the test. 
   */
  public int getTestIndice() {
    return this.testIndice;
  }

  /**
   * Sets unit test execution result. 
   *  
   * @param success Success value string.
   */
  public void setSuccessValue(String success) {
    this.success = success;    
  }

  /**
   * Check test succeeds or not.
   * 
   * @return True if test succeeds.
   */
  public boolean isSuccessful() {
    return "true".equals(this.success) || "pass".equals(this.success);
  }

  /**
   * Sets test case name.
   * 
   * @param testcase Name of the test case. 
   */
  public void setTestCase(String testcase) {
    this.testcase = testcase;
  }
  
  /**
   * Gets test case name.
   * 
   * @return Name of the test case.
   */
  public String getTestCase() {
    return this.testcase;
  }
  
  /**
   * Sets unit test failure message. 
   * 
   * @param failureMessage Failure message if this unit test fails.
   */
  public void setFailureMessage(String failureMessage) {
    this.success = "failure";
    this.failureMessage = failureMessage;
  }
  
  /**
   * Gets unit test failure message. 
   * 
   * @return Failure message if this unit test unit fails.
   */
  public String getFailureMessage() {
    return this.failureMessage;
  }
  
  /**
   * Makes Jess facts in the given Jess rete engine.
   * 
   * @param index Action index in episode. 
   * @param engine Jess rete engine.
   * @throws JessException If error while constructing jess action.
   * @return Jess fact of this action.
   */
  @Override public Fact assertActivity(int index, Rete engine) throws JessException  {
    Fact f = new Fact("UnitTestActivity", engine);
    f.setSlotValue(INDEX_SLOT, new Value(index, RU.INTEGER));

    String file = super.extractFileName(super.getResourceUri());
    f.setSlotValue(FILE_SLOT, new Value(file, RU.STRING));
    if (!this.isSuccessful()) {
      f.setSlotValue("errmsg", new Value(this.success, RU.STRING));
    }
    
    Fact assertedFact = engine.assertFact(f);
    return assertedFact;
  }  
  
  
  /**
   * Gets the run time of unit test.
   *  
   * @return Run time. 
   */
  public XMLGregorianCalendar getRunTime() {
    return this.runTime;
  }

  /**
   * Gets the elapsed time of testing.
   *  
   * @return Elapsed time. 
   */
  public int getElapsedTime() {
    return this.elapsedTime;
  }
  

  /**
   * Gets unit test action string.
   * 
   * @return Unit test action string. 
   */
  @Override public String toString() {
    return super.toString() + " " + this.getRepresentation();
  }

  /** Get the representation of this activity. 
   * 
   * @return String representation of this activity.
   */
  @Override public String getRepresentation() {
    if (this.isSuccessful()) {
      return "PASSED";
    }
    else {
      return "FAILED";
    }
  }
}
